package com.udp.nml.example;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.net.SocketAddress;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Example UDP Handler Adapter showing how to read individual bytes from a UDP message.
 * 
 * @author Niall McLoughlin
 */
public class UDPHandler extends IoHandlerAdapter 
{
	static Logger logger = LoggerFactory.getLogger(UDPHandler.class);
	
	private PropertyChangeSupport pcs = new PropertyChangeSupport(this);
	
	private String logText = new String();
	
	public String getLogText() 
	{
		return logText;
	}

	public void setLogText(String logText) 
	{
		String oldValue = this.logText;
		
		if (logText.length() > 5000)
		{
			logText = logText.substring((logText.length() - 5000));
		}
		this.logText = logText;
		pcs.firePropertyChange("logText", oldValue, logText);
	}

	public UDPHandler()
	{
		
	}
	
	public UDPHandler(PropertyChangeListener propertyChangeListener)
	{
		pcs.addPropertyChangeListener("logText", propertyChangeListener);
	}
	
	@Override
	public void messageReceived(IoSession session, Object message)
			throws Exception 
	{		
        logger.info(">>> messageReceived");
        
		if (message instanceof IoBuffer) 
        {
            // Cast the message to an IoBuffer. 
			// The basic DatagramSocket messages arrive as an IoBuffer and the 
			// Apache Mina version does too.
			IoBuffer buffer = (IoBuffer) message;
			
			Packet packet = new Packet(buffer);
			
			// Get the address of the remote client.
            SocketAddress remoteAddress = session.getRemoteAddress();

            StringBuffer logMessage = new StringBuffer();
            logMessage.append("Remote Address:");
            logMessage.append(remoteAddress);
            logMessage.append("Incoming Packet:");
            logMessage.append(packet);
            
            // Log the message.
            logger.info(logMessage.toString());
            
            handleIncomingPacket(session, packet);
        } 
		
		logger.info("<<< messageReceived");
	}
	
	private void handleIncomingPacket(IoSession session, Packet packet)
	{
		logger.info(">>> sendAcknowledgement");
		
		PacketType incomingPacketType = PacketType.getType(packet.getType());
		
		if (PacketType.UNIT_ID.equals(incomingPacketType))
		{
			Packet returnPacket = new Packet();
			returnPacket.setType(PacketType.REG_DATA.getByteValue());
			returnPacket.setSerialNumber(packet.getSerialNumber());
			returnPacket.setData("UNITIDRESPONSEFROMHANDLER".getBytes());
			
			logger.info("Sending Response: " + returnPacket);

			byte[] responseAsBytes = returnPacket.getBytes();
			UDPUtils.sendBytesOnSession(session, responseAsBytes);
		}
		else if (PacketType.GOT_REG.equals(incomingPacketType))
		{
			Packet returnPacket = new Packet();
			returnPacket.setType(PacketType.ERROR.getByteValue());
			returnPacket.setSerialNumber(packet.getSerialNumber());
			returnPacket.setData("GOTREGRESPONSEFROMHANDLER".getBytes());
			
			logger.info("Sending Response: " + returnPacket);

			byte[] responseAsBytes = returnPacket.getBytes();
			UDPUtils.sendBytesOnSession(session, responseAsBytes);
		}
        
        logger.info("<<< sendAcknowledgement");
	}
	
	@Override
	public void sessionCreated(IoSession session) throws Exception 
	{
		logger.info(">>> sessionCreated");
		
		super.sessionCreated(session);
		
		logger.info("<<< sessionCreated");
	}
	
	@Override
	public void sessionClosed(IoSession session) throws Exception 
	{
		logger.info(">>> sessionClosed");
		
		super.sessionClosed(session);
		
		logger.info("<<< sessionClosed");
	}
	
	@Override
	public void messageSent(IoSession session, Object message) throws Exception 
	{
		logger.info(">>> messageSent");
		
		super.messageSent(session, message);
		
		logger.info("<<< messageSent");
	}
}